package ro.gillardon.business.polling;

import java.io.IOException;

import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import ro.gillardon.commons.Price;
import ro.gillardon.commons.config.ConfigParam;
import ro.gillardon.commons.config.ConfigProvider;
import ro.gillardon.commons.enums.Currency;
import ro.gillardon.commons.enums.Hotel;
import ro.gillardon.commons.hotel.HotelDetailsWrapper;
import ro.gillardon.commons.logger.BTPLogger;

/**
 * Parser class for the Achat hotel from Bretten.
 *
 * @author lorinczi
 */

public final class AchatBrettenParser {

  /** Regular expression for non numeric characters. */
  private static final String NON_NUMERIC_CHARS = "[^\\d.]";

  /**
   * Log4j logging.
   */
  private static final Logger LOG = Logger.getLogger(AchatBrettenParser.class);

  private static final String HTTP_HOST = ConfigProvider.getProperty(ConfigParam.HTTP_PROXY_HOST);
  private static final String HTTP_PORT = ConfigProvider.getProperty(ConfigParam.HTTP_PROXY_PORT);
  private static final String HOTEL_URL = ConfigProvider.getProperty(ConfigParam.ACHAT_BRETTEN_URL);

  /**
   * Private Constructor.
   */
  private AchatBrettenParser() {
  }

  /**
   * Method connects to a wrbsite and gets the content.
   */
  private static Document connectAndGetContent() throws IOException {

    System.setProperty("http.proxyHost", HTTP_HOST);
    System.setProperty("http.proxyPort", HTTP_PORT);

    return Jsoup.connect(HOTEL_URL).get();
  }

  /**
   * Gets the price from the content.
   */
  public static HotelDetailsWrapper parseDocumentAndGetPriceInformation(final Document document) {

    Element documentContent = document.getElementById("text-content");
    Elements divs = documentContent.getElementsByClass("hotel_midcont");
    Elements rows = divs.select("tr");

    try {
      HotelDetailsWrapper wrapper = new HotelDetailsWrapper();

      double breakfastPrice = getParsedBreakfastPrice(rows.get(1).text());
      parseSingleAndDoubleRoomPriceAndSetValues(wrapper, rows.get(0), breakfastPrice);

      return wrapper;
    } catch (NumberFormatException e) {
      BTPLogger.error(LOG, "Error: parsing price values for hotel Achat-Bretten");
      return null;
    }
  }

  /**
   * Parse the element and set the prices in the wrapper.
   */
  private static void parseSingleAndDoubleRoomPriceAndSetValues(final HotelDetailsWrapper wrapper,
    final Element element,
    final double breakfast) {

    wrapper.setHotel(Hotel.ACHAT_BRETTEN);
    String[] priceInformationContainer = element.text().split(" ");

    setPriceForSingleRoom(wrapper, breakfast, priceInformationContainer);

    setPriceForDoubleRoom(wrapper, breakfast, priceInformationContainer);

  }

  private static void setPriceForDoubleRoom(final HotelDetailsWrapper wrapper, final double breakfast,
    final String[] priceInformationContainer) {
    double price = parsePriceFromInformationContainer(priceInformationContainer[9], breakfast);
    wrapper.setDoubleRoomWeekdayPrice(new Price(price, Currency.EUR));
    wrapper.setDoubleRoomWeekendPrice(new Price(price, Currency.EUR));
  }

  private static void setPriceForSingleRoom(final HotelDetailsWrapper wrapper, final double breakfast,
    final String[] priceInformationContainer) {
    double price = parsePriceFromInformationContainer(priceInformationContainer[2], breakfast);

    wrapper.setSingleRoomWeekdayPrice(new Price(price, Currency.EUR));
    wrapper.setSingleRoomWeekendPrice(new Price(price, Currency.EUR));
  }

  private static double parsePriceFromInformationContainer(final String priceInformationContainer,
    final double breakfast) {
    String value = priceInformationContainer.replaceAll(",", ".").replaceAll(NON_NUMERIC_CHARS, "");

    return breakfast + Double.parseDouble(value);
  }

  private static double getParsedBreakfastPrice(final String stringToParse) {
    String[] value = stringToParse.split(" ");
    return Double.parseDouble(value[1].replaceAll(",", ".")
      .replaceAll(NON_NUMERIC_CHARS, ""));
  }

  /**
   * getLatestPrice method, gets the price from the webpage and returns it in a wrapper.
   *
   * @return wrapper - wrapper for hotel details
   */
  public static HotelDetailsWrapper getLatestPrice() {

    try {
      Document document = connectAndGetContent();
      return parseDocumentAndGetPriceInformation(document);

    } catch (IOException e) {
      BTPLogger.error(LOG, "Connection problem: " + e);
      return null;
    }

  }

}
